#ifndef __IM_VALUE_H__
#define __IM_VALUE_H__

#include <im_base_types.h>
#include <im_object.h>

/**
 * @defgroup IMValue
 * @ingroup PublicIME
 * @{
 */

/** @struct IMValue
 *  @brief A container object which can hold one datum,
 *         The datum can be a bool, a char/uchar, an int32/uint32,
 *         an int64/uint64, a double, a pointer, a string or an object.
 */

IM_BEGIN_DECLS

#define IM_VALUE(p)             (IM_TYPE_INSTANCE_CHECK_CAST((p),IM_TYPE_VALUE,IMValue))
#define IM_CONST_VALUE(p)       (IM_TYPE_INSTANCE_CHECK_CAST_CONST((p),IM_TYPE_VALUE,IMValue))
#define IM_VALUE_CLASS(c)       (IM_TYPE_CLASS_CHECK_CAST((c),IM_TYPE_VALUE,IMValueClass))
#define IM_IS_VALUE(p)          (IM_TYPE_INSTANCE_CHECK_TYPE((p),IM_TYPE_VALUE))
#define IM_IS_VALUE_CLASS(c)    (IM_TYPE_CLASS_CHECK_TYPE((c),IM_TYPE_VALUE))
#define IM_VALUE_GET_CLASS(p)   (IM_TYPE_INSTANCE_GET_CLASS_CAST((p),IM_TYPE_VALUE,IMValueClass))

#define IM_VALUE_TYPE(p)        (im_value_get_value_type (p))
#define IM_VALUE_TYPE_NAME(p)   (im_type_get_name(IM_VALUE_TYPE(p)))

typedef struct _IMValue         IMValue;
typedef struct _IMValueClass    IMValueClass;


/**
 * @brief Create a new zero-filled IMValue object.
 *
 * The im_value_new() function shall allocate 
 * 
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new                ();
/**
 * @brief Create a new IMValue object that holds a char value.
 *
 * @param v_char a char value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_char           (IMChar              v_char);
/**
 * @brief Create a new IMValue object that holds a unsigned char value.
 *
 * @param v_uchar an unsigned char value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_uchar          (IMUChar             v_uchar);
/**
 * @brief Create a new IMValue object that holds a bool value.
 *
 * @param v_bool a bool value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_bool           (IMBool              v_bool);
/**
 * @brief Create a new IMValue object that holds an int16 value.
 *
 * @param v_int16 an int16 value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_int16          (IMInt16             v_int16);
/**
 * @brief Create a new IMValue object that holds a unsigned int16 value.
 *
 * @param v_uint16 a unsinged int16 value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_uint16         (IMUInt16            v_uint16);
/**
 * @brief Create a new IMValue object that holds an int32 value.
 *
 * @param v_int32 an int32 value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_int32          (IMInt32             v_int32);
/**
 * @brief Create a new IMValue object that holds a unsigned int32 value.
 *
 * @param v_uint32 a unsinged int32 value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_uint32         (IMUInt32            v_uint32);
/**
 * @brief Create a new IMValue object that holds an int64 value.
 *
 * @param v_int64 an int64 value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_int64          (IMInt64             v_int64);
/**
 * @brief Create a new IMValue object that holds a unsigned int64 value.
 *
 * @param v_uint64 a unsinged int64 value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_uint64         (IMUInt64            v_uint64);
/**
 * @brief Create a new IMValue object that holds a double value.
 *
 * @param v_double a double value to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_double         (IMDouble            v_double);
/**
 * @brief Create a new IMValue object that holds a pointer.
 *
 * @param v_pointer a pointer to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_pointer        (IMPointer           v_pointer);
/**
 * @brief Create a new IMValue object that holds a string.
 *
 * @param *v_string a string to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_c_string       (const IMChar       *v_string);
/**
 * @brief Create a new IMValue object that holds a static string.
 *
 * @param *v_string a string to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_static_c_string(const IMChar       *v_string);
/**
 * @brief Create a new IMValue object that takes an ownership of a newly allocated string.
 *
 * @param *v_string a string to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_take_c_string  (IMChar             *v_string);
/**
 * @brief Create a new IMValue object that holds an object.
 *
 * @param v_pointer a pointer to an object to be filled into the new IMValue object.
 *
 * @return IMValue* a new IMValue object.
 */
IMValue*        im_value_new_object         (IMPointer           v_object);

/**
 * @brief Get the value type of a value holded in a IMValue object.
 *
 * The im_value_get_value_type() function shall return a type of the data which the value contains.
 * IM_TYPE_INVALID shall be returned if the value is a null pointer, or is not a IMValue object instance,
 * or has no data.
 *
 * @param *value a IMValue object.
 * @return IMType a type name of the variant that has been filled into the IMValue object.
 */
IMType          im_value_get_value_type     (const IMValue      *value);

/**
 * @brief Clear the value of a IMValue object.
 *
 * The im_value_clear() function shall clear the data stored in value.
 *
 * After calling im_value_clear() function, the data previously stored in the value is clear and
 * a type of data the value holds shall be IM_TYPE_INVALID.
 *
 * @param *value a IMValue object.
 * @return The im_value_clear() function shall not return a value.
 */
void            im_value_clear              (IMValue            *value);

/**
 * @brief Store a char value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_char a char value to be stored into the IMValue object.
 *
 * @return The im_value_set_char() function shall not return a value.
 */
void            im_value_set_char           (IMValue            *value,
                                             IMChar              v_char);
/**
 * @brief Get the char value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMChar a char value.
 */
IMChar          im_value_get_char           (const IMValue      *value);
/**
 * @brief Store a unsigned char value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_uchar a unsigned char value to be stored into the IMValue object.
 *
 * @return The im_value_set_uchar() function shall not return a value.
 */
void            im_value_set_uchar          (IMValue            *value,
                                             IMUChar             v_uchar);
/**
 * @brief Get the unsigned char value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMUChar an unsigned char value.
 */
IMUChar         im_value_get_uchar          (const IMValue      *value);
/**
 * @brief Store a bool value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_bool a bool value to be stored into the IMValue object.
 *
 * @return The im_value_set_bool() function shall not return a value.
 */
void            im_value_set_bool           (IMValue            *value,
                                             IMBool              v_bool);
/**
 * @brief Get the bool value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMBool a bool value.
 */
IMBool          im_value_get_bool           (const IMValue      *value);
/**
 * @brief Store an int16 value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_int32 an int16 value to be stored into the IMValue object.
 *
 * @return The im_value_set_int16() function shall not return a value.
 */
void            im_value_set_int16          (IMValue            *value,
                                             IMInt16             v_int32);
/**
 * @brief Get the int16 value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMUInt16 a unsigned int32 value.
 */
IMInt16         im_value_get_int16          (const IMValue      *value);
/**
 * @brief Store a unsigned int16 value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_uint32 a unsigned int16 value to be stored into the IMValue object.
 *
 * @return The im_value_set_uint16() function shall not return a value.
 */
void            im_value_set_uint16         (IMValue            *value,
                                             IMUInt16            v_uint32);
/**
 * @brief Get the unsigned int16 value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMUInt16 a unsigned int32 value.
 */
IMUInt16        im_value_get_uint16         (const IMValue      *value);
/**
 * @brief Store an int32 value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_int32 an int32 value to be stored into the IMValue object.
 *
 * @return The im_value_set_int32() function shall not return a value.
 */
void            im_value_set_int32          (IMValue            *value,
                                             IMInt32             v_int32);
/**
 * @brief Get the int32 value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMInt32 an int32 value.
 */
IMInt32         im_value_get_int32          (const IMValue      *value);
/**
 * @brief Store a unsigned int32 value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_uint32 a unsigned int32 value to be stored into the IMValue object.
 *
 * @return The im_value_set_uint32() function shall not return a value.
 */
void            im_value_set_uint32         (IMValue            *value,
                                             IMUInt32            v_uint32);
/**
 * @brief Get the unsigned int32 value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMUInt32 a unsigned int32 value.
 */
IMUInt32        im_value_get_uint32         (const IMValue      *value);
/**
 * @brief Store an int64 value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_int64 an int64 value to be stored into the IMValue object.
 *
 * @return The im_value_set_int64() function shall not return a value.
 */
void            im_value_set_int64          (IMValue            *value,
                                             IMInt64             v_int64);
/**
 * @brief Get the int64 value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMInt64 an int64 value.
 */
IMInt64         im_value_get_int64          (const IMValue      *value);
/**
 * @brief Store a unsigned int64 value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_uint64 a unsigned int64 value to be stored into the IMValue object.
 *
 * @return The im_value_set_uint64() function shall not return a value.
 */
void            im_value_set_uint64         (IMValue            *value,
                                             IMUInt64            v_uint64);
/**
 * @brief Get the unsigned int64 value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMUInt64 a unsigned int64 value.
 */
IMUInt64        im_value_get_uint64         (const IMValue      *value);
/**
 * @brief Store a double value into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_double a double value to be stored into the IMValue object.
 *
 * @return The im_value_set_double() function shall not return a value.
 */
void            im_value_set_double         (IMValue            *value,
                                             IMDouble            v_double);
/**
 * @brief Get the double value holded in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMDouble a double value.
 */
IMDouble        im_value_get_double         (const IMValue      *value);
/**
 * @brief Store a pointer into a IMValue object.
 *
 * @param *value a IMValue object.
 * @param v_pointer a pointer to be stored into the IMValue object.
 *
 * @return The im_value_set_pointer() function shall not return a value.
 */
void            im_value_set_pointer        (IMValue            *value,
                                             IMPointer           v_pointer);
/**
 * @brief Get the pointer value that is held in a IMValue object.
 *
 * @param *value a IMValue object.
 *
 * @return IMPointer a Pointer.
 */
IMPointer       im_value_get_pointer        (const IMValue      *value);

/**
 * @brief Store a string into a IMValue object.
 *
 * The IMValue object will hold a copy of the string. So the original
 * string can be freed or modified afterwards.
 *
 * @param *value a IMValue object.
 * @param *v_string a string to be stored into the IMValue object.
 *
 * @return The im_value_set_c_string() function shall not return a value.
 */
void            im_value_set_c_string       (IMValue            *value,
                                             const IMChar       *v_string);

/**
 * @brief Store a static string into a IMValue object.
 *
 * The IMValue object will just hold the original pointer, and won't free
 * it when destroying.
 *
 * So the string must not be freed or modified before destroying the value
 * object.
 *
 * @param *value a IMValue object.
 * @param *v_string a string to be stored into the IMValue object.
 *
 * @return The im_value_set_static_c_string() function shall not return a value.
 */
void            im_value_set_static_c_string(IMValue            *value,
                                             const IMChar       *v_string);

/**
 * @brief Take an ownership holded in a newly allocated string.
 *
 * The im_value_take_c_string() function shall 
 * The string will be freed when destroying the IMValue object.
 *
 * @param *value a IMValue object.
 * @param *v_string a string to be stored into the IMValue object.
 *
 * @return The im_value_take_c_string() function shall not return a value.
 */
void            im_value_take_c_string      (IMValue            *value,
                                             IMChar             *v_string);

/**
 * @brief Get the string held by an IMValue object.
 *
 * The im_value_get_c_string() function shall return a pointer to the string contained in
 * the IMValue object pointed by value.
 * A null pointer is returned if the datum contained in the IMValue object is not string, or
 * the value argument is a null pointer.
 *
 * The string pointed to by the return value shall not be modified or freed.
 *
 * @param value a pointer to an  IMValue object.
 *
 * @return The im_value_get_c_string() function shall return a pointer to the string 
 *          in type of IMChar * on success, Otherwise it shall return a null pointer.
 */
const IMChar*   im_value_get_c_string       (const IMValue      *value);

/**
 * @brief im_value_dup_c_string - duplicate a string in an IMValue object
 *
 * The im_value_dup_c_string() function shall return a pointer to a new string,
 * which is a duplicate of the string contained in the IMValue object pointed by
 * value. The returned pointer can be passed to im_free(). A null pointer is
 * returned if the new string cannot be created or the datum contained in the
 * IMValue object is not a string.
 *
 * @param value a pointer to an IMValue object.
 *
 * @return The im_value_dup_c_string() function shall return a pointer to a new string
 *         in type of IMChar* on success. Otherwise it shall return a null pointer.
 */
IMChar*         im_value_dup_c_string       (const IMValue      *value);

/**
 * @brief Store an object into a IMValue object.
 *
 * The reference count of the object will be increased, so that it won't
 * be destroyed before destroying the IMValue object.
 *
 * @param *value  a IMValue object.
 * @param v_object an object to stored.
 *
 * @return The im_value_set_object() shall not return a value.
 */
void            im_value_set_object         (IMValue            *value,
                                             IMPointer           v_object);

/**
 * @brief Get the object holded b a IMValue object.
 *
 * The im_value_get_object() function shall return a pointer to an IMObject,
 * 
 * A null pointer is returned if the value is a null pointer, or the value doesn't containe
 * a pointer to an IMObject.
 *
 * Pointer to the object will be returned. If this object will continue to
 * be used afer destroying the IMValue object, im_object_ref() should be called
 * against it to increase its reference count.
 *
 * @param *value  a IMValue object.
 *
 * @return IMPointer a Pointer to object.
 *
 * @see im_value_dup_object
 */
IMPointer       im_value_get_object         (const IMValue      *value);

/**
 * @brief Duplicate the object holded by a value.
 *
 * The im_value_dup_object() function shall return a pointer to a IMObject,
 * which is a duplicate of the IMObject that the value holds.
 *
 * The returned IMPointer can be passed to im_object_unref().
 *
 * A null pointer is returned if the value is a null pointer, or the value doesn't contain
 * a pointer to an IMObject.
 *
 * @param *value  an IMValue object.
 *
 * @return The im_value_dup_object() function shall return IMPointer points to an IMObject which is hold by value.
 * 
 */
IMPointer       im_value_dup_object         (const IMValue      *value);


IM_END_DECLS
/** @} */

#endif
/*
vi:ts=4:nowrap:ai:expandtab
*/
